package dbrpc

import (
	"bytes"
	"database/sql"
	"dub/define/grpcmodel"
	"dub/utils"
	"fmt"
	"golang.org/x/net/context"
	"regexp"
)

type DbRpcRegion struct {
	log *utils.Logger
}

//查询一个行政区信息
func (r *DbRpcRegion) FindRegion(ctx context.Context, args *grpcmodel.ModelDbRpcRegionReqFind) (reply *grpcmodel.ModelDbRpcRegionResFindRegion, err error) {
	reply = &grpcmodel.ModelDbRpcRegionResFindRegion{}
	dbAccounts := NewDbProxy().Get(DB_Accounts)
	sql_str := "select regionCode from dubregion where regionCode=? limit 1"
	r.log.Infof("def_func_db_region.go FindRegion method exec %s params is %+v\n", sql_str, args.GetRegionCode())
	row := dbAccounts.QueryRow(sql_str, args.GetRegionCode())
	var regionCode sql.NullString
	err = row.Scan(&regionCode)

	switch {
	case err == sql.ErrNoRows:
		err = nil
		reply.Err = 1
	case err != nil:
		reply.Err = 2
		r.log.Errorf("def_fun_db_region.go FindRegion method row.scan err. %v\n", err)
	default:
		reply.ModelDbRpcRegion = &grpcmodel.ModelDbRpcRegion{}
		if regionCode.Valid {
			reply.ModelDbRpcRegion.RegionCode = regionCode.String
		}
	}
	return
}

//查询行政区
func (r *DbRpcRegion) Find(ctx context.Context, args *grpcmodel.ModelDbRpcRegionReqFind) (reply *grpcmodel.ModelDbRpcRegionResFind, err error) {
	reply = &grpcmodel.ModelDbRpcRegionResFind{}
	for {
		if args.GetRegionLevel() < 1 {
			args.RegionLevel = 1
		}
		buf := bytes.Buffer{}
		params := make([]interface{}, 0)
		buf.WriteString("select regionId,regionName,regionCode,regionLev from dubregion where 1=1")
		if !args.GetIsFindAll() {
			buf.WriteString(" and regionLev=?")
			params = append(params, args.GetRegionLevel())
		}

		//如果是非一级则PreCode必须要有值
		if args.GetRegionLevel() > 1 && !args.GetIsFindAll() {
			if args.GetPreCode() == "" {
				reply.Err = 3
				break
			}
			preCode := args.GetPreCode()
			if args.GetRegionLevel() != 2 && args.GetRegionLevel() != 3 {
				reply.Err = 3
				break
			}

			if args.GetRegionLevel() == 2 {
				first, _ := regexp.MatchString("^[1-9][0-9]{1}0000", args.GetPreCode())
				if !first {
					reply.Err = 3
					break
				} else {
					args.PreCode = fmt.Sprintf("^%s[0-9]{4}", args.GetPreCode()[:2])
				}
			}
			if args.GetRegionLevel() == 3 {
				two, _ := regexp.MatchString("^[1-9][0-9]{3}00", args.GetPreCode())
				if !two {
					reply.Err = 3
					break
				} else {
					args.PreCode = fmt.Sprintf("^%s[0-9]{2}", args.GetPreCode()[:4])
				}
			}
			buf.WriteString(" and regionCode regexp ? and regionCode!=?")
			params = append(params, args.GetPreCode())
			params = append(params, preCode)
		}

		dbAccounts := NewDbProxy().Get(DB_Accounts)
		sql_str := buf.String()
		r.log.Infof("def_func_db_region.go Find method exec %s params is %+v\n", sql_str, params)
		rows, err := dbAccounts.Query(sql_str, params...)
		if err == sql.ErrNoRows {
			err = nil
			reply.Err = 1
			break
		}
		if err != nil && err != sql.ErrNoRows {
			reply.Err = 2
			r.log.Errorf("def_fun_db_region.go Find method dbAccounts.Query err.%v\n", err)
			break
		}

		defer rows.Close()
		reply.Rows = make([]*grpcmodel.ModelDbRpcRegion, 0)
		for rows.Next() {
			var (
				regionId, regionLev    sql.NullInt64
				regionName, regionCode sql.NullString
			)
			err := rows.Scan(&regionId, &regionName, &regionCode, &regionLev)
			if err != nil {
				reply.Err = 2
				r.log.Errorf("def_fun_db_region.go Find method rows.Scan err.%v\n", err)
				continue
			}
			tmp_region := grpcmodel.ModelDbRpcRegion{}
			if regionId.Valid {
				tmp_region.RegionId = uint32(regionId.Int64)
			}
			if regionLev.Valid {
				tmp_region.RegionLev = uint32(regionLev.Int64)
			}
			if regionName.Valid {
				tmp_region.RegionName = regionName.String
			}
			if regionCode.Valid {
				tmp_region.RegionCode = regionCode.String
			}
			reply.Rows = append(reply.Rows, &tmp_region)
		}
		break
	}
	return
}

var d_dbRpcRegion *DbRpcRegion

func NewDbRpcRegion() *DbRpcRegion {
	if d_dbRpcRegion == nil {
		d_dbRpcRegion = &DbRpcRegion{
			log: utils.NewLogger(),
		}
	}
	return d_dbRpcRegion
}
